/**
 * LY.com Inc.
 * Copyright (c) 2004-2020 All Rights Reserved.
 */
package com.gitee.kamismile.stone.rpc.core.handler.impl.provider.producer;

import com.gitee.kamismile.stone.commmon.exception.BusinessException;
import com.gitee.kamismile.stone.rpc.api.invocation.IStoneFilter;
import com.gitee.kamismile.stone.rpc.api.invocation.support.StoneInvocation;
import com.gitee.kamismile.stone.rpc.common.engine.StoneRpcContext;
import com.gitee.kamismile.stone.rpc.common.errorenum.RpcErrorEnum;
import com.gitee.kamismile.stone.rpc.common.exception.RPCException;
import com.gitee.kamismile.stone.rpc.common.invocation.IStoneAsyncResponse;
import com.gitee.kamismile.stone.rpc.common.invocation.StoneInvocationType;
import com.gitee.kamismile.stone.rpc.common.provider.consumer.StoneConsumerMeta;
import com.gitee.kamismile.stone.rpc.common.provider.producer.StoneProviderMeta;
import com.gitee.kamismile.stone.rpc.common.support.StoneURL;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @author dong.li
 * @version $Id: ProviderVersionChooseHandleImpl, v 0.1 2020/4/3 10:55 dong.li Exp $
 */
@Component
public class VersionProducerChooseFilter implements IStoneFilter {

    @Override
    public StoneInvocationType getInvocationType() {
        return StoneInvocationType.PRODUCER;
    }

    @Override
    public int order() {
        return 0;
    }


    @Override
    public void handle(StoneInvocation stoneInvocation, IStoneAsyncResponse asyncResp) throws Exception {
        StoneProviderMeta stoneProviderMeta = stoneInvocation.getStoneProviderMeta();
        StoneURL currentStone = stoneInvocation.getStoneURL();

        int retry = currentStone.getRetry();
        int i = 0;
        while (i <= retry) {
            i++;
            try {
                StoneURL versionStone = StoneConsumerMeta.findVersion(stoneProviderMeta);

                currentStone.setHost(versionStone.getHost());
                currentStone.setPort(versionStone.getPort());
                currentStone.getParameters().putAll(versionStone.getParameters());

                if (versionStone.getCallsAtomic().get() < Integer.MAX_VALUE) {
                    versionStone.getCallsAtomic().getAndIncrement();
                }

                StoneRpcContext.getLocalContext().setChooseStoneURL(versionStone);

                stoneInvocation.next(asyncResp);
                versionStone.getAndIncrement();
                versionStone.getCallAndIncrement();
            } catch (RPCException rpcException) {
//                decrementWeight(-10);
                //服务方离线
//                if (rpcException.getCode() == RpcErrorEnum.SERVERCLOSE.getCode()) {
//                }

                if(RpcErrorEnum
                        .OUTTIME.getCode()==rpcException.getCode()||RpcErrorEnum
                        .SENDSERVER.getCode()==rpcException.getCode()){
                    decrementWeight(-3);
                }else {
                    decrementWeight(-80);
                }
                StoneRpcContext.removeContext();
//                if ((rpcException.getCode() != RpcErrorEnum.CREATESERVER.getCode()) || i > retry) {
                if ( i > retry) {
                    throw new BusinessException(rpcException.getCode(),rpcException.getMessage());
                }
            }
        }

    }


    private static void decrementWeight(int delta) {
        StoneURL chooseStoneURL = StoneRpcContext.getLocalContext().getChooseStoneURL();
        if (!Objects.isNull(chooseStoneURL)) {
            if (chooseStoneURL.getWeight() > 50 || delta < -10) {
                chooseStoneURL.getWeightAtomic().addAndGet(delta);
            } else {
                chooseStoneURL.getAndDecrement();
            }
        }
    }


}
